package MemoryManagement.Test;

import java.util.*;

import MemoryManagement.Memory;
import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.*;

public class MemoryTest {

    @Test
    public void writePage_validInput_dataWrittenSuccessfully() {
        // Arrange
        int pageIndex = 10;
        int startOffset = 100;
        byte[] data = {1, 2, 3, 4, 5};

        // Act
        Memory.writePage(pageIndex, startOffset, data);

        // Assert
        byte[] writtenData = Arrays.copyOfRange(Memory.byteArray, pageIndex * Memory.pageSize +
                startOffset, pageIndex * Memory.pageSize + startOffset + data.length);
        Assert.assertArrayEquals(data, writtenData);
    }

     @Test
     public void writePage_invalidPageIndex_throwsIllegalArgumentException() {
         // Arrange
         int pageIndex = -1;
         int startOffset = 100;
         byte[] data = {1, 2, 3, 4, 5};

         // Act & Assert
         assertThrows(IllegalArgumentException.class, () -> Memory.writePage(pageIndex, startOffset, data));
     }

    @Test
    public void writePage_invalidStartOffset_throwsIllegalArgumentException() {
        // Arrange
        int pageIndex = 10;
        int startOffset = -1;
        byte[] data = {1, 2, 3, 4, 5};

        // Act & Assert
        assertThrows(IllegalArgumentException.class, () -> Memory.writePage(pageIndex, startOffset, data));
    }

    @Test
    public void writePage_dataIsNull_throwsIllegalArgumentException() {
        // Arrange
        int pageIndex = 10;
        int startOffset = 100;
        byte[] data = null;

        // Act & Assert
        assertThrows(IllegalArgumentException.class, () -> Memory.writePage(pageIndex, startOffset, data));
    }

    @Test
    public void writePage_dataExceedsPageSize_throwsIllegalArgumentException() {
        // Arrange
        int pageIndex = 10;
        int startOffset = 100;
        byte[] data = new byte[Memory.pageSize - startOffset + 1];

        // Act & Assert
        assertThrows(IllegalArgumentException.class, () -> Memory.writePage(pageIndex, startOffset, data));
    }

    @Test
    public void readPage_validInput_returnsCorrectData() {
        // Arrange
        int pageIndex = 10;
        int startOffset = 100;
        int length = 5;
        byte[] expectedData = {1, 2, 3, 4, 5};
        Memory.writePage(pageIndex, startOffset, expectedData);

        // Act
        byte[] actualData = Memory.readPage(pageIndex, startOffset, length);

        // Assert
        assertArrayEquals(expectedData, actualData);
    }

    @Test
    public void initializePhysicBlock_allBlocksAreFalse() {
        // Arrange
        Memory.initializePhysicBlock();

        // Act & Assert
        for (boolean block : Memory.PhysicBlock) {
            assertFalse(block);
        }
    }


    @Test
    public void findFreeBlock_blockFoundWithinRange_returnsBlockIndex() {
        // Arrange
        Memory.initializePhysicBlock();
        int start = 0;
        int end = 10;

        // Act
        int freeBlockIndex = Memory.findFreeBlock(start, end);

        // Assert
        assertTrue(freeBlockIndex >= start && freeBlockIndex < end);
        assertTrue(Memory.PhysicBlock[freeBlockIndex]);
    }


    @Test
    public void freeBlock_validBlock_blockIsFreed() {
        // Arrange
        Memory.initializePhysicBlock();
        int block = 5;
        Memory.PhysicBlock[block] = true;

        // Act
        Memory.freeBlock(block);

        // Assert
        assertFalse(Memory.PhysicBlock[block]);
    }
}
